#include "double-linked-list.h"

Node::Node(Object *object, Node *previous, Node *next)
{
	OBJECT = object;
	PREVIOUS = previous;
	NEXT = next;

}

Node::~Node()
{
	if (PREVIOUS != NULL)
		PREVIOUS->NEXT = NEXT;
	if (NEXT != NULL)
		NEXT->PREVIOUS = PREVIOUS;
//	delete OBJECT;
}

Node *Node::next()
{
	return NEXT;
}

Node *Node::previous()
{
	return PREVIOUS;
}

Object *Node::object()
{
	return OBJECT;
}

void Node::setNext(Node *next)
{
	NEXT = next;
}


Double_Linked_List::Double_Linked_List()
{
	HEAD = NULL;
	TAIL = HEAD;
	SIZE = 0;
}

Double_Linked_List::~Double_Linked_List()
{
	if (SIZE == 0)
		return;
		
	Node *temp;
	TAIL = NULL;
	
	while (HEAD != NULL)
	{
		temp = HEAD;
		HEAD = HEAD->next();
		delete temp;
	}
}

// This function returns true if the list contains a pointer to the specified object. It returns false otherwise.
bool Double_Linked_List::contains(Object *obj)
{
	Node *temp = HEAD;
	while (temp != NULL)
	{
		if (temp->object() == obj)
			return true;
		temp = temp->next();
	}
	return false;
}

bool Double_Linked_List::isEmpty()
{
	if (SIZE == 0)
		return true;
	else
		return false;
}

int Double_Linked_List::size()
{
	return SIZE;
}

Object *Double_Linked_List::isAt(int position)
{
	Node *temp;
	temp = HEAD;
	
	if (position >= SIZE)
		return NULL;
		
	for (int i=0; i<position; i++)
	{
		temp = temp->next();
	}
	
	return temp->object();
}

Object *Double_Linked_List::pop()
{
	if (TAIL == NULL)
		return NULL;
	
	Node *temp = TAIL;	
	Object *object = temp->object();
	if (TAIL == HEAD)	// If this is the only element.
	{
		HEAD = NULL;
		TAIL = NULL;
	}
	else
		TAIL = TAIL->previous();
		
	delete temp;
	SIZE--;
	return object;
}
	

Node *Double_Linked_List::head()
{
	return HEAD;
}

Node *Double_Linked_List::node(int position)
{
	Node *temp = HEAD;
	
	if (position >= SIZE)
		return NULL;
		
	for (int i=0; i<position; i++)
	{
		temp = temp->next();
	}
	
	return temp;
}

Node *Double_Linked_List::tail()
{
	return TAIL;
}

void Double_Linked_List::add(Object *object)
{
	if (SIZE == 0)
	{
		HEAD = new Node(object, NULL, NULL);
		TAIL = HEAD;
	}
	else
	{
		TAIL->setNext(new Node(object, TAIL, NULL));
		TAIL = TAIL->next();
	}
	SIZE++;
}

void Double_Linked_List::push(Object *object)
{
	add(object);
}

void Double_Linked_List::remove(Object *object)
{
	Node *temp = HEAD;
	
	while (temp != NULL)
	{
		if (temp->object() == object)
		{
			delete temp;
			SIZE--;
			return;
		}
		temp = temp->next();
	}
}

